 /*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 /**
 * Project  : kindlepush
 * Package  : net.solosky.kindlepush.book
 * File     : EpubBookBuilder.java
 * Author   : solosky < solosky772@qq.com >
 * Created  : 2012-4-21
 * License  : Apache License 2.0 
 */
package net.solosky.kindlepush.forum.book;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import net.solosky.kindlepush.forum.bean.Post;
import net.solosky.kindlepush.forum.bean.Topic;
import net.solosky.kindlepush.util.DateUtils;

import org.jsoup.Jsoup;

import com.adobe.dp.epub.io.DataSource;
import com.adobe.dp.epub.io.OCFContainerWriter;
import com.adobe.dp.epub.ncx.TOCEntry;
import com.adobe.dp.epub.opf.NCXResource;
import com.adobe.dp.epub.opf.OPSResource;
import com.adobe.dp.epub.opf.Publication;
import com.adobe.dp.epub.opf.Resource;
import com.adobe.dp.epub.opf.StyleResource;
import com.adobe.dp.epub.ops.Element;
import com.adobe.dp.epub.ops.HyperlinkElement;
import com.adobe.dp.epub.ops.ImageElement;
import com.adobe.dp.epub.ops.OPSDocument;
import com.adobe.dp.epub.style.Rule;
import com.adobe.dp.epub.style.Selector;
import com.adobe.dp.epub.style.Stylesheet;
import com.itextpdf.text.BadElementException;


/**
 *
 * 生成epub的电子书实现
 *
 * @author solosky <solosky772@qq.com>
 *
 */
public class EpubBookBuilder implements BookBuilder {
	private Publication epub;
	private StyleResource style;
	public EpubBookBuilder(){
	    epub = new Publication();

	    // create a stylesheet
	    style = epub.createStyleResource("OPS/styles.css");
	    Stylesheet stylesheet = style.getStylesheet();
	    
	 // style h1 element
	    Selector bodySelector = stylesheet.getSimpleSelector("body", null);
	    Rule bodyRule = stylesheet.getRuleForSelector(bodySelector);
	    bodyRule.set("margin", "0px");
	    bodyRule.set("padding", "0px");

	    // style h1 element
	    Selector h1Selector = stylesheet.getSimpleSelector("h1", null);
	    Rule h1Rule = stylesheet.getRuleForSelector(h1Selector);
	    h1Rule.set("color", "gray");
	    h1Rule.set("border-bottom", "2px solid gray");
	    h1Rule.set("text-align", "right");
	    h1Rule.set("margin", "2em 8px 1em 0px");

	    Selector pSelector = stylesheet.getSimpleSelector("p", null);
	    Rule pRule = stylesheet.getRuleForSelector(pSelector);
	    pRule.set("margin", "0px");
	    pRule.set("text-indent", "1em");
	    pRule.set("text-align", "justify");
	}

	@Override
	public void writeTopic(String chapterName, Topic topic) throws Exception {
		epub.addDCMetadata("title", topic.getTitle());
		epub.addDCMetadata("creator", "www.kindlepush.com EpubBuilder");
		epub.addDCMetadata("language", "zh_CN");
		
	    OPSResource chapter = epub.createOPSResource("OPS/intro.html");
	    epub.addToSpine(chapter);
	    
		NCXResource toc = epub.getTOC();
		OPSDocument doc = chapter.getDocument();
		doc.addStyleResource(style);
		
		TOCEntry rootTOCEntry = toc.getRootTOCEntry();
	    TOCEntry chapter1TOCEntry = toc.createTOCEntry(chapterName, doc.getRootXRef());
	    rootTOCEntry.add(chapter1TOCEntry);
	    
	    Element body1 = doc.getBody();
	    Element header1 = doc.createElement("h3");
	    header1.add(topic.getTitle());
	    
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(header1);
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    body1.add(doc.createElement("br"));
	    
	    Element info = doc.createElement("p");
	    info.add("作者: "+topic.getAuthor());
	    info.add(doc.createElement("br"));
	    info.add("发表时间: "+DateUtils.formatDate(topic.getPostDate()));
	    info.add(doc.createElement("br"));
	    info.add("网址: "+topic.getMainUrl());
	    info.add(doc.createElement("br"));
	    info.add("由 www.kindlepush.com 创建");
	    
	    body1.add(info);
	}

	@Override
	public void writePosts(String chapterName, String sectionName, List<Post> posts) throws Exception {
		NCXResource toc = epub.getTOC();
		Iterator it = toc.getRootTOCEntry().content();
		Random rand = new Random();
		boolean isFirst = false;
		
		TOCEntry chapterTOCEntry = null;
		while(it.hasNext()){
			TOCEntry entry = (TOCEntry) it.next();
			if(entry.getTitle().equals(chapterName)){
				chapterTOCEntry = entry;
				break;
			}
		}
		
		if(chapterTOCEntry==null){
			OPSResource chapter = epub.createOPSResource("OPS/"+chapterName+".html");
			epub.addToSpine(chapter);
			chapterTOCEntry = toc.createTOCEntry(chapterName, chapter.getDocument().getRootXRef());
			toc.getRootTOCEntry().add(chapterTOCEntry);
		    isFirst = true;
		}
		
		OPSResource section = epub.createOPSResource("OPS/"+chapterName+"-"+sectionName+".html");
		epub.addToSpine(section);
		TOCEntry sectionEnry = toc.createTOCEntry(sectionName, section.getDocument().getRootXRef());
		chapterTOCEntry.add(sectionEnry);
		
		
		OPSDocument doc = section.getDocument();
		Element body = doc.getBody();
		doc.addStyleResource(style);
		
		if(isFirst){
		    Element chapterHeader = doc.createElement("h2");
		    chapterHeader.add(chapterName);
		    body.add(chapterHeader);
		}
		
		Element sectionHeader = doc.createElement("h3");
		sectionHeader.add(sectionName);
	    body.add(sectionHeader);
		
		for(Post post: posts){

			StringBuffer buffer = new StringBuffer();
			buffer.append("<h5>");
			buffer.append("==============================================================<br />");
			buffer.append("# ");
			buffer.append(post.getFloor());
			buffer.append("楼   作者：");
			buffer.append(post.getAuthor());
			buffer.append("  发表时间：");
			buffer.append(DateUtils.formatDate(post.getDate()==null ? new Date():post.getDate()));
			buffer.append("<br />");
			buffer.append("==============================================================<br />");
			buffer.append("</h5>");
			buffer.append("<p>");
			buffer.append(post.getText());
			buffer.append("</p>");
			
			body.add(buildNode(Jsoup.parse(buffer.toString()).body(), doc));
		}
	}

	@Override
	public void saveBook(File file) throws Exception {
		OCFContainerWriter writer = new OCFContainerWriter(new FileOutputStream(file));
		epub.serialize(writer);
	}
	
	
	private com.adobe.dp.epub.ops.Element buildNode(org.jsoup.nodes.Node node, OPSDocument doc) throws BadElementException, MalformedURLException, IOException{
		if(node instanceof org.jsoup.nodes.TextNode){
			Element span = doc.createElement("span");
			span.add(((org.jsoup.nodes.TextNode) node).text());
			return span;
		}else if(node instanceof org.jsoup.nodes.Element){
			org.jsoup.nodes.Element el = (org.jsoup.nodes.Element) node;
			String tagName = el.tagName().toLowerCase();
			if(tagName.equals("br")){
				return doc.createElement("br");
			}else if(tagName.equals("img")){
				Element span = doc.createElement("span");
				span.add("[图片]");
				return span;
			}else if(tagName.equals("a")){
				HyperlinkElement a = doc.createHyperlinkElement(el.text());
				a.setExternalHRef(el.attr("href"));
				return a;
			}else{
				Element p = doc.createElement(tagName);
				p.setClassName(el.attr("class"));
				p.setId(el.attr("id"));
				List<org.jsoup.nodes.Node> children = el.childNodes();
				for(org.jsoup.nodes.Node child: children){
					p.add(buildNode(child, doc));
				}
				return p;
			}
		}else{
			throw new IllegalStateException("unexpected node type:"+node);
		}
	}


}
